package com.wb.adutils

import android.app.Activity
import android.content.Context
import android.text.TextUtils
import android.widget.Toast
import com.bytedance.msdk.api.v2.GMAdConfig
import com.bytedance.msdk.api.v2.GMMediationAdSdk
import com.bytedance.msdk.api.v2.GMPangleOption
import com.bytedance.sdk.openadsdk.TTAdConfig
import com.bytedance.sdk.openadsdk.TTAdConstant
import com.bytedance.sdk.openadsdk.TTAdSdk
import com.bytedance.sdk.openadsdk.TTCustomController
import com.wb.adutils.db.AdEntity
import com.wb.adutils.db.AdRoomUtils
import com.wb.adutils.tools.*
import org.json.JSONObject
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.lang.Exception
import java.lang.NullPointerException
import java.lang.ref.WeakReference

object AdUtils {


    /** 开屏广告兜底广告 穿山甲 */
    const val TYPE_PANGLE = 0
    /** 开屏广告兜底广告 优亮汇 */
    const val TYPE_GDT = 1
    // 兜底广告参数
    // o: 穿山甲，1：优亮汇
    private lateinit var appId: String
    private lateinit var appName: String
    // 开屏兜底广告位id
    private var adUnit: String? = null
    private var deviceId: String? =null
    private var type: Int = TYPE_PANGLE
    private var isDebugModel = false
    // 配置本地广告
    private var adLocalCacheJson: JSONObject? = null
    private lateinit var contextWeak: WeakReference<Context>

    fun initAd(context: Context): AdUtils {
        contextWeak = WeakReference(context)
        // 根据条件是否清空广告内容
        if (SPUtil.getInstance(context).isNextStartClearAd) {
            SPUtil.getInstance(context).isNextStartClearAd = false
            clearAdList()
        }
        // 更新时间
        updateShowTime()
        return this
    }

    fun getContext(): Context? {
        return contextWeak.get()
    }

    // 设置广告的部分参数
    fun setAppInfo(appId: String, appName: String): AdUtils{
        this.appId = appId
        this.appName = appName
        return this
    }

    fun setDebugModel(isDebugModel: Boolean) : AdUtils{
        this.isDebugModel = isDebugModel
        return this
    }

    fun setDeviceId(deviceId: String?): AdUtils{
        this.deviceId = deviceId
        return this
    }

    // "ad_local_cache_0730.json"
    fun setLocalConfig(assetsFileName: String): AdUtils{
        val adLocalCacheStr = loadPemFromAssetFile(assetsFileName)
        if (!TextUtils.isEmpty(adLocalCacheStr)) {
            adLocalCacheJson = JSONObject(adLocalCacheStr)
            LogC.e("配置本地缓存 ->")
        }
        return this
    }


    fun setGMNetworkRequestInfo(type: Int, adUnit: String) : AdUtils{
        this.type = type
        this.adUnit = adUnit
        return this
    }

    fun build(){
        val context = getContext()
        if (context == null) {
            LogC.e("context is null")
            return
        }
        if (TextUtils.isEmpty(appId) || TextUtils.isEmpty(appName)) {
            throw NullPointerException("appId or appName is null")
        }

        if (isDebugModel) {
            appId = "5227980"
            appName = "testDemo"
            adUnit = "887861265"
        }
        initGMMediationAd(context)
    }


    fun getAdType(): Int{
        return type
    }

    fun getAppId(): String{
        return appId
    }

    fun getSplashAdUnit(): String?{
        return adUnit
    }

    fun isDebugModel(): Boolean {
        return isDebugModel
    }

    fun getDeviceId(context: Context): String{
        return if (TextUtils.isEmpty(deviceId)) {
            DeviceIdUtil.getDeviceId(context)
        } else {
            deviceId!!
        }
    }

    /**
     * 获取广告列表
     */
    fun getAdList(): List<AdEntity>? {
        return AdRoomUtils.getInstance()?.adDao()?.queryAll()
    }

    /**
     * 更新广告列表
     */
    fun insertAdList(ads: ArrayList<AdEntity>?){
        LogC.e("准备更新广告内容...")
        if (isDebugModel) {
            LogC.e("测试模式...获取测试列表...")
            RxUtils.doObservable<Int> {
                val adDao = AdRoomUtils.getInstance()?.adDao()
                adDao?.deleteAll()
                LogC.e("测试模式...删除旧的广告内容...")
                val testAds = getTestAdList()
                testAds.forEach { adEntity ->
                    if (adEntity.adTemplate == AdConstants.AD_TEMPLATE_DOWNLOAD) {
                        if (adEntity.userDownloadCount < 0) {
                            adEntity.userDownloadCount = adEntity.downloadDefaultCount
                        }
                    }
                    LogC.e("测试模式...更新${getNameByTemplate(adEntity.adTemplate)}广告...${adEntity.advertiser}, ${adEntity.adUnit}")
                    adDao?.insert(adEntity)
                }
                it.onComplete()
            }
        } else {
            RxUtils.doObservable<Int> {
                val adDao = AdRoomUtils.getInstance()?.adDao()
                adDao?.deleteAll()
                LogC.e("删除旧的广告内容...")
                if (ads.isNullOrEmpty()) {
                    it.onComplete()
                    return@doObservable
                }
                ads.forEach {
                    // 下载广告，更新用户下载次数
                    if (it.adTemplate == AdConstants.AD_TEMPLATE_DOWNLOAD) {
                        if (it.userDownloadCount < 0) {
                            it.userDownloadCount = it.downloadDefaultCount
                        }
                    }
                    LogC.e("更新${getNameByTemplate(it.adTemplate)}广告......${it.advertiser}, ${it.adUnit}")
                    adDao?.insert(it)
                }
                it.onComplete()
            }
        }
    }

    /**
     * 是否第一次加载广告，目前只用在详情广告的提前判断
     */
    fun isFirstLoadAd(activity: Activity): Boolean {
        val isFirstLoad = SPUtil.getInstance(activity).isFirstLoad
        if (isFirstLoad) {
            SPUtil.getInstance(activity).isFirstLoad = false
            RxUtils.doObservable<Int> {
                val adDao = AdRoomUtils.getInstance()?.adDao()
                val ad = adDao?.queryAd(AdConstants.AD_TEMPLATE_VIDEO)
                if (ad == null) {
                    it.onComplete()
                    return@doObservable
                }
                LogC.e("查询是否第一次加载，并更新视频广告的展示时间...")
                ad.showTime = System.currentTimeMillis()
                adDao.update(ad)
                it.onComplete()
            }
        }
        return isFirstLoad
    }

    /**
     * 是否跳过广告，目前只用在详情广告的提前判断
     */
    fun isSkipAd(template: Int): Boolean{
        val adEntity = AdRoomUtils.getInstance()?.adDao()?.queryAd(template)?:return true
        return System.currentTimeMillis() <= adEntity.showTime + adEntity.adInterval * 1000L
    }

    /**
     * 通过模板获取广告
     */
    fun getAdByTemplate(template: Int): AdEntity? {
        return AdRoomUtils.getInstance()?.adDao()?.queryAd(template)
    }

    /**
     * 更新广告
     */
    fun updateAd(ad: AdEntity?){
        if (TextUtils.isEmpty(ad?.adUnit)) return
        RxUtils.doObservable<Int> {
            AdRoomUtils.getInstance()?.adDao()?.update(ad!!)
            it.onComplete()
        }
    }

    /**
     * 清空广告列表
     * @param isNextStartClear 是否下次启动时清除广告
     */
    fun clearAdList(isNextStartClear: Boolean = false){
        RxUtils.doObservable<Int> {
            if (isNextStartClear) {
                val context = getContext()
                if (context == null) {
                    LogC.e("context is null")
                    it.onComplete()
                    return@doObservable
                }
                SPUtil.getInstance(context).isNextStartClearAd = true
            } else {
                AdRoomUtils.getInstance()?.adDao()?.deleteAll()
            }
            it.onComplete()
        }

    }


    /**
     * 初始化广告
     */
    private fun initGMMediationAd(context: Context) {
        try {

            initGMAdapter(context)


        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun initGMAdapter(context: Context){
        //强烈建议在应用对应的Application#onCreate()方法中调用，避免出现content为null的异常
        val pangleConfig = GMPangleOption.Builder()
            .setAllowShowNotify(true) // 是否允许sdk展示通知栏提示,若设置为false则会导致通知栏不显示下载进度
            .setIsUseTextureView(true) //是否支持多进程，true支持
            .build()

        val adConfig = GMAdConfig.Builder()
            .setAppId(appId)
            .setAppName(appName)
            .setDebug(isDebugModel)
            .setOpenAdnTest(isDebugModel)
            .setPangleOption(pangleConfig)    //设置穿山甲配置参数
            .setCustomLocalConfig(adLocalCacheJson)
            .setPrivacyConfig(PrivacyConfig(getDeviceId(context)))
            .build()

        //针对穿山甲模板渲染信息流&插屏&Banner广告新增接口设置夜间模式设置
        // 进行夜间模式的设置 ，其中 0: 正常模式 1: 夜间模式
        GMMediationAdSdk.setThemeStatus(0)

        GMMediationAdSdk.initialize(context, adConfig)
    }

    private fun initPangleAd(context: Context) {
        // 单独的 穿山甲广告
        val config = TTAdConfig.Builder()
            .appId(appId)
            .useTextureView(true) //默认使用SurfaceView播放视频广告,当有SurfaceView冲突的场景，可以使用TextureView
            .appName(appName)
            .titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)//落地页主题
            .allowShowNotify(false) //是否允许sdk展示通知栏提示,若设置为false则会导致通知栏不显示下载进度
            .debug(isDebugModel) //测试阶段打开，可以通过日志排查问题，上线时去除该调用
            .directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI) //允许直接下载的网络状态集合,没有设置的网络下点击下载apk会有二次确认弹窗，弹窗中会披露应用信息
            .supportMultiProcess(true) //是否支持多进程，true支持
            .build()
        config.customController = object: TTCustomController(){

            override fun getDevOaid(): String {
                return getDeviceId(context)
            }

        }

        TTAdSdk.init(context, config, object :  TTAdSdk.InitCallback{
            override fun success() {

            }

            override fun fail(p0: Int, p1: String?) {
                LogC.e("广告初始化 失败 -> " + p1)
            }
        })
    }

    private fun updateShowTime (){
        RxUtils.doObservable<Int> {
            val adDao = AdRoomUtils.getInstance()?.adDao()
            val ads = adDao?.queryAll()
            if (ads.isNullOrEmpty()) {
                it.onComplete()
                return@doObservable
            }
            ads.forEach {
                if (it.clearCache == 1) {
                    it.showTime = 0
                }
                adDao.update(it)
            }
        }
    }


    /**
     * 根据模板获取广告名称
     */
    fun getNameByTemplate(template: Int): String{
        return when (template) {
            AdConstants.AD_TEMPLATE_SPLASH, 1200000000 -> "开屏"
            AdConstants.AD_TEMPLATE_VIDEO, 1200000001 -> "详情页插屏/激励"
            AdConstants.AD_TEMPLATE_VIDEO_BANNER, 1200000002 -> "详情页信息流"
            AdConstants.AD_TEMPLATE_VIDEO_PAUSE, 1200000003 -> "暂停"
            AdConstants.AD_TEMPLATE_DOWNLOAD, 1200000004 -> "下载激励"
            AdConstants.AD_TEMPLATE_EXIT, 1200000005 -> "退出"
            AdConstants.AD_TEMPLATE_VIDEO_PRE, 1200000006 -> "贴片"
            AdConstants.AD_TEMPLATE_REOPEN, 1200000007 -> "Reopen"
            AdConstants.AD_TEMPLATE_HOME_LIST, 1200000008 -> "Home列表"
            else -> "unknown"
        }
    }
    /**
     * 从asset文件读取证书内容
     * @param context
     * @return 证书字符串
     */
    private fun  loadPemFromAssetFile(assetsFileName: String): String {
        val context = contextWeak.get()?:return "null"
        return try {
            val inputStream = context.assets.open(assetsFileName)
            val br = BufferedReader(InputStreamReader(inputStream))
            val builder = StringBuilder()
            var line: String?
            while ((br.readLine().also { line = it }) != null){
                builder.append(line)
                builder.append('\n')
            }
            builder.toString();
        } catch ( e: IOException) {
            LogC.e("loadPemFromAssetFile failed");
            ""
        }
    }



    private fun getTestAdList(): ArrayList<AdEntity> {
        val advertiser = 1
        val ads = ArrayList<AdEntity>()

        // 退出
        val bannerAd = AdEntity()
        bannerAd.adTemplate = AdConstants.AD_TEMPLATE_EXIT
        bannerAd.advertiser = advertiser
        bannerAd.adUnit = if (bannerAd.advertiser == 0) {
            "949418198"
        } else {
            "102110609"
//            "947535211"
        }
        bannerAd.adInterval = 0
        bannerAd.adType = 0
        bannerAd.clearCache = 0
        bannerAd.downloadDefaultCount = 10
        bannerAd.downloadAddCount = 2
        bannerAd.timeout = 10
        bannerAd.txt = ""
        ads.add(bannerAd)


        // 详情页 信息流
        val native = AdEntity()
        native.adTemplate = AdConstants.AD_TEMPLATE_VIDEO_BANNER
        native.advertiser = advertiser
        native.adUnit = if (native.advertiser == 0) {
            "949418194"
        } else {
            "102111101"
//            "947557357"
        }
        native.adInterval = 0
        native.adType = 1
        native.clearCache = 0
        native.downloadDefaultCount = 10
        native.downloadAddCount = 2
        native.timeout = 60

        ads.add(native)


        // 详情页 插屏/激励
        val interstitial = AdEntity()
        interstitial.adTemplate = AdConstants.AD_TEMPLATE_VIDEO
        interstitial.advertiser = advertiser
        interstitial.adUnit = if (interstitial.advertiser == 0) {
            "949418204"
        } else {
            "102110851"
//            "947552814"
        }
        // 广告请求间隔，以秒为单位
        interstitial.adInterval = 60 * 10
        // 广告类型，主要是给详情广告使用，有插屏和激励  插屏0：激励：1
        interstitial.adType = 1
        interstitial.clearCache = 0
        interstitial.downloadDefaultCount = 10
        interstitial.downloadAddCount = 2
        interstitial.timeout = 10
        native.txt = "详情页广告600s加载一次"
        ads.add(interstitial)


        // 详情暂停
        val pause = AdEntity()
        pause.adTemplate = AdConstants.AD_TEMPLATE_VIDEO_PAUSE
        pause.advertiser = advertiser
        pause.adUnit = if (pause.advertiser == 0) {
            "949418194"
        } else {
            "102111101"
//            "947248153"
        }
        pause.adInterval = 0

        pause.adType = 0
        pause.clearCache = 0
        pause.downloadDefaultCount = 10
        pause.downloadAddCount = 2
        pause.timeout = 10
        pause.txt = ""
        ads.add(pause)



        // 下载激励
        val reward = AdEntity()
        reward.adTemplate = AdConstants.AD_TEMPLATE_DOWNLOAD
        reward.advertiser = advertiser
        reward.adUnit = if (reward.advertiser == 0) {
            "949418209"
        } else {
            "102110907"
//            "948086702"
        }
        // 广告请求间隔，以秒为单位
        reward.adInterval = 60
        // 广告类型，主要是给详情广告使用，有插屏和激励  插屏0：激励：1
        reward.adType = 0
        reward.clearCache = 0
        reward.downloadDefaultCount = 10
        reward.downloadAddCount = 2
        reward.timeout = 10
        ads.add(reward)

        // 开屏
        val open = AdEntity()
        open.adTemplate = AdConstants.AD_TEMPLATE_SPLASH
        open.advertiser = advertiser
        open.adUnit = if (open.advertiser == 0) {
            "887866804"
        } else {
            "102110195"
//            "887661589"
        }
        // 广告请求间隔，以秒为单位
        open.adInterval = 0
        // 广告类型，主要是给详情广告使用，有插屏和激励  插屏0：激励：1
        open.adType = 0
        open.clearCache = 0
        open.downloadDefaultCount = 10
        open.downloadAddCount = 2
        open.timeout = 10
        ads.add(open)


        // 列表
        val homeList = AdEntity()
        homeList.adTemplate = AdConstants.AD_TEMPLATE_HOME_LIST
        homeList.advertiser = advertiser
        homeList.adUnit = if (homeList.advertiser == 0) {
            "949418194"
        } else {
            "102111101"
//            "947557084"
        }
        // 广告请求间隔，以秒为单位
        homeList.adInterval = 0
        // 广告类型，主要是给详情广告使用，有插屏和激励  插屏0：激励：1
        homeList.adType = 0
        homeList.clearCache = 0

        homeList.downloadDefaultCount = 10
        homeList.downloadAddCount = 2
        homeList.timeout = 10
        ads.add(homeList)
        return ads
    }
}